package com.fourhats.controller;

import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.imageio.IIOException;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.fourhats.model.ObjectTypes;
import com.fourhats.security.CustomUser;
import com.fourhats.services.MarketService;
import com.fourhats.services.VisitEntityService;
import com.fourhats.services.dto.MarketDto;
import com.fourhats.services.dto.PublicMarketDto;
import com.fourhats.services.util.FileHelper;
import com.fourhats.services.util.ImageInfo;
import com.fourhats.services.util.Page;
import com.google.gson.Gson;

@Controller
public class MarketController extends GenericController {

	@Autowired
	private MarketService marketService;
	
	@Autowired
	private VisitEntityService entityVisitService;
	
	@Value("#{configProps}")
	private Properties properties;
	
	private final String SMALL_MARKET_FOLDER = "small";
	private final String MEDIUM_MARKET_FOLDER = "medium";
	private final String LARGE_MARKET_FOLDER = "large";
	private final String ORIGINAL_FOLDER = "originals";
	
	/*Temp*/
	private final String ORIGINAL_TEMP_FOLDER = "originals";
	
	@RequestMapping("/markets")
    public String goToMarkets(Model model) {
        return "content/markets";
	}
	
	@RequestMapping("/market/detail/{marketId}/{marketName}")
	public String goToMarketDetail(@PathVariable long marketId, @PathVariable String marketName, Model model) {
		PublicMarketDto market = marketService.getPublicMarketById(marketId);
		boolean isOwner = market.getUserId().equals(this.getUserId());
		
		if(!isOwner) {
			this.entityVisitService.addVisitEntity(ObjectTypes.MARKET.getValue(), marketId, this.getUserId());
			if(!market.isEnable()) {
				return "redirect:/home";
			}
		}
		
		Gson gson = new Gson();
		model.addAttribute("market", gson.toJson(market).toString());
        model.addAttribute("isOwner", isOwner);
        
        return "content/marketDetail";
	}
	
	@RequestMapping("/market/marketCreation")
    public String goToCreateMarket(ModelMap model) {
		return getMarketCreationView(model, new MarketDto(super.getUserId()));
	}
	
	@RequestMapping("/market/marketCreation/{marketId}")
    public String goToEditMarket(@PathVariable long marketId, ModelMap model) {
		MarketDto market = marketService.getMarketById(marketId);
		if (market == null) {
			return "redirect:/home";
		}
			
		try {
			if(market.getUserId() != super.getUserId()) {
				return "redirect:/home";
			}
			
		} catch (Exception e) {
			return "redirect:/home";
		}
		
		return getMarketCreationView(model, market);
	}
	
	@RequestMapping(value = "/market/updateMarket", method = RequestMethod.POST)
    public String updateMarket(@ModelAttribute("marketAttribute") MarketDto market, BindingResult result, HttpServletRequest request, HttpServletResponse response, Model model) throws Exception {
		if(marketService.existMarketWithName(market.getName(), this.getUserId())) {
			model.addAttribute("existMarketWithSameName", "true");
			return "content/marketCreation";
		}
		
		if(market.getId() == 0){
			createMarket(model, market);	
		} else {
			try {
				if(market.getUserId() != super.getUserId()) {
					return "redirect:/home";
				}
			} catch (Exception e) {
				return "redirect:/home";
			}
			
			editMarket(model, market);
		}
		
		return "redirect:/user/profile";
	}
	
	@RequestMapping(value="/market/desactivateMarket")
	public @ResponseBody void desactivateMarket(long marketId) {
		marketService.desactivateMarket(marketId);
	}
	
	@RequestMapping(value="/market/activateMarket")
	public @ResponseBody void activateMarket(long marketId) {
		marketService.activateMarket(marketId);
	}
	
	@RequestMapping(value = "/markets/getAllMarkets", 
	method = RequestMethod.GET, 
	headers="Accept=*/*")
	public @ResponseBody Page<MarketDto> getAllMarkets(int pageNumber, int pageSize) {
		return marketService.getAllMarkets(pageNumber, pageSize);
	}
	
	
	@RequestMapping(value = "/markets/getMarketsPageByKeyword", 
	method = RequestMethod.GET, 
	headers="Accept=*/*")
	public @ResponseBody Page<MarketDto> getMarketsPageByKeyword(String keyword, int pageNumber, int pageSize) {
		return this.marketService.getMarketsPageByKeyword(keyword, pageNumber, pageSize );
	}
	
	
	@RequestMapping(value = "/market/getMarketById", 
	method = RequestMethod.GET, 
	headers="Accept=*/*")
	public @ResponseBody MarketDto getMarketById(long marketId){
		return marketService.getMarketById(marketId);
	}
	
	
	@RequestMapping(value = "/market/getMarketByUser", 
	method = RequestMethod.GET, 
	headers="Accept=*/*")
	public @ResponseBody MarketDto getMarketByUser(long userId){
		return marketService.getMarketByUser(userId);
	}
	
	private String getMarketCreationView(ModelMap model, MarketDto marketDto){
		try {
			super.verifyAuthentication();
		} catch (Exception e) {
			return "redirect:/home"; 
		}
		
		Gson gson = new Gson();
		
		model.addAttribute("market", gson.toJson(marketDto));
		model.addAttribute("marketAttribute", marketDto);
		return "content/marketCreation";
	}
	
	private void createMarket(Model model, MarketDto market) throws Exception{
		market.setEnable(true);
		CustomUser customUser = (CustomUser)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		marketService.createMarket(market, customUser.getId());
		copyImageFromTemp(market);
		model.addAttribute("successMarketCreation", true);
	}
	
	private void editMarket(Model model, MarketDto market) throws Exception{
		marketService.editMarket(market);
		copyImageFromTemp(market);
		model.addAttribute("successMarketEdition", true);
	}

	private void copyImageFromTemp(MarketDto market) throws Exception {
		String tempPath = properties.getProperty("folder.temp");
		String marketPath = properties.getProperty("folder.market");
		
		if(market.getImagePath() == "") {
			return;
		}
		
		List<ImageInfo> imagesInfo = new ArrayList<ImageInfo>();
		imagesInfo.add(new ImageInfo(SMALL_MARKET_FOLDER, 125, 100));
		imagesInfo.add(new ImageInfo(MEDIUM_MARKET_FOLDER, 275, 191));
		
		BufferedImage imageSrc = null;
		try{
			File file = new File(tempPath, market.getImagePath());
			imageSrc = ImageIO.read(file);
			byte [] imageBytes = FileHelper.bufferedImageToByte(imageSrc, FilenameUtils.getExtension(market.getImagePath()));
			imagesInfo.add(new ImageInfo(LARGE_MARKET_FOLDER, imageSrc.getWidth(), imageSrc.getHeight()));
			FileHelper.generateImages2(imageBytes, marketPath, market.getImagePath(), imagesInfo);
			
			String src = FileHelper.getFullPath(tempPath, ORIGINAL_TEMP_FOLDER, market.getImagePath());
			String dst = FileHelper.getFullPath(marketPath, ORIGINAL_FOLDER, market.getImagePath());
			FileHelper.copyFile(src, dst);
		} catch(IIOException iioE){
			iioE.printStackTrace();
		} catch(Exception e){
			throw e;
		} finally{
			if(imageSrc != null){
				imageSrc.flush();
			}
		}
	}
}
